

var Widget = Widget || {};

// UI namespace in Widget namespace (NOTE: var keyword causes sytax error why??) 
Widget.UI = Widget.UI || {};

(function(){
	
	/**
	 * Feedback component
	 */
	Widget.Feedback = {};
	
	// topLeft, topRight, bottomLeft,  centerRight, bottomRight
	Widget.Feedback.ALIGN_TOP_LEFT = 'topLeft';
	Widget.Feedback.ALIGN_TOP_RIGHT = 'topRight'; 
	Widget.Feedback.ALIGN_BOTTOM_LEFT = 'bottomLeft';
	Widget.Feedback.ALIGN_BOTTOM_RIGHT = 'bottomRight';
	Widget.Feedback.ALIGN_CENTER_RIGHT = 'centerRight';
	
	Widget.Feedback.error = function(selector, message, options) {
		Widget.Feedback._message(selector, 'error', message, options);
	}
	Widget.Feedback.info = function(selector, message, options) {
		Widget.Feedback._message(selector, 'pass', message, options);
	}
	Widget.Feedback.hide = function (selector) {
		$.validationEngine.closePrompt(selector,true);
	}
	Widget.Feedback.hideAll = function() {
		$.validationEngine.closePrompt('.formError',true);
	}
	
	Widget.Feedback._message = function (selector, type, message, options) {
		Widget.Feedback._init(options);
		$.validationEngine.buildPrompt(selector, message, type);
	}
	
	Widget.Feedback._init = function(options) {
		if (typeof($.validationEngine.settings) == 'undefined') {
			$.validationEngine.defaultSetting();
		}
		
		if (typeof(options) != 'undefined') {
			if (typeof(options.align) != 'undefined') {
				$.validationEngine.settings.promptPosition = options.align;
			}
		}
		
	}
	
	/**
	 * Validator component
	 * 
	 * NOTE: There is a bug in validator engine therefore to enable closing
	 * prompt by click on it a validationEngine is needed to instantiate.
	 */
	Widget.Validator = {};
	
	Widget.Validator.validate = function(validators, options) {

		var invalid = false;
		for (var i = 0; i < validators.length; i++) {

			var vOptions = options;
			if (typeof(validators[i].options) != 'undefined') {
				vOptions = validators[i].options;
			}
			
			Widget.Feedback._init(vOptions);
			
			var vRules = [];
			for (var j = 0; j < validators[i].rules.length; j++) {

				var rule = validators[i].rules[j];
				if (typeof (rule) == 'string') {
					vRules.push(rule);
				} else if (typeof(rule) == 'object' && typeof(rule.type) != 'undefined') {
					
					switch (rule.type) {
					
					case 'custom':
						_init_rule(rule.name);
						
						$.validationEngine.settings.allrules[rule.name].regex = rule.regex;
						
						if (typeof(rule.alertText) != 'undefined') {
							$.validationEngine.settings.allrules[rule.name].alertText = rule.alertText;
						}
						
						vRules.push('custom');
						vRules.push(rule.name);
						break;
					
					case 'func':
						_init_rule(rule.name);
						
						$.validationEngine.settings.allrules[rule.name].nname = '_________' + rule.name; 
						window[$.validationEngine.settings.allrules[rule.name].nname] = rule.fn;
						
						if (typeof(rule.alertText) != 'undefined') {
							$.validationEngine.settings.allrules[rule.name].alertText = rule.alertText;
						}

						vRules.push('funcCall');
						vRules.push(rule.name);
						break;
					
					
					}
				}
				
				invalid = $.validationEngine.validateCall(validators[i].selector, vRules) || invalid;
				
				// HOT FIX: if the next validator returns false then the
				// messagebox will be disappeared therefore we break this loop
				if (invalid) {
					break;
				}
			}
				
		}
		
		function _init_rule(name) {
			if (typeof($.validationEngine.settings.allrules[name]) == 'undefined') {
				$.validationEngine.settings.allrules[name] = { };
			}
		}
		
		return !invalid;
	}
	

	/**
	 * Common view related classes
	 */
	Widget.Dimension = function(width, height) {
		this.width = width;
		this.height = height;
	}
	
	Widget.View = Class.extend({
		
		init: function(name) {
			this.name = name;
		},
		
		updateModel: function(model) {
			this.model = model;
		},
		
		preferedSize: function() {
			var container = $('#' + this.name + 'Container');
			return new Widget.Dimension(this._width(container), this._height(container));
		},
		
		controls: function() {
			return [];
		},
		
		_width: function(e) {
			var cssWidth = e.css('width');
			return cssWidth.replace('px', '');
		},
		
		_height: function(e) {
			var cssHeight = e.css('height');
			return cssHeight.replace('px', '');
		},
		
		// Callback, if view is hidden
		_onHide: function() {
		},
		
		// Callback, if view is shown 
		_onShow: function() {
		}
	});
	
	/**
	 * Toolbar 
	 */
	Widget.UI.Docked = Widget.View.extend({
		
		// Constructor
		init: function() {
			this._super(Widget.UI.Docked._name);
			
			// Static initializer
			Widget.Utils.initializeSingleton(Widget.UI.Docked, this);
		},
		
		updateModel: function(model) {
			this._super(model);
			
			$('#dockedView #unitSelector').html('');
			$.each(model, function(index, unit) {
				$('#dockedView #unitSelector').append('<option value=\'' + unit.name + '\'>' + unit.name + '</option>');
			});
		},
		
		_width: function(e) {
		},
		
		_height: function(e) {
		},
		
		controls: function() {
			return ['hideButton', 'configButton', 'autoChallengeButton', 'challengeButton'];
		}
		
	});
	
	// Static methods & properties
	Widget.UI.Docked._name = 'dockedView';
	Widget.UI.Docked.instance = function() {
		return Widget.Utils.singletonInstance(Widget.UI.Docked, true);
	}
	
	/**
	 * Config view
	 */
	Widget.UI.Config = Widget.View.extend({
		
		// Constructor
		init: function() {
			this._super(Widget.UI.Config._name);
			
			// Static initializer
			Widget.Utils.initializeSingleton(Widget.UI.Config, this);
		},
		updateModel: function(model) {
			this._super(model);
			
			if (model.units.length > 0) {
				$('#configView #removeUnit').removeClass('disabled');
				$('#configView #editUnit').removeClass('disabled');
			} else {
				$('#configView #removeUnit').addClass('disabled');
				$('#configView #editUnit').addClass('disabled');
			}
			
			$('#configView #unitList').html('');
			$.each(model.units, function(index, unit) {
				$('#configView #unitList').append('<option value=\'' + unit.name + '\'>' + unit.name + '</option>');
			});
			
			$('#configView #autoChallengeTime').val(model.config.autoChallengeTime);
			if (model.config.autoHide) {
				$('#configView #autoHide').attr('checked', 'yes');
			} else {
				$('#configView #autoHide').removeAttr('checked');
			}
		}
	});
	
	// Static methods & properties
	Widget.UI.Config._name = 'configView';
	Widget.UI.Config.instance = function() {
		return Widget.Utils.singletonInstance(Widget.UI.Config, true);
	}
	
	/**
	 * Unit view
	 */
	Widget.UI.UnitEdit = Widget.View.extend({
		
		// Constructor
		init: function() {
			this._super(Widget.UI.UnitEdit._name);
			
			$('#unitEditView #unitType').html('');
			
			var types = Widget.UnitManager.instance().types();
			for (var i in types) {
				$('#unitEditView #unitType').append('<option value=\'' + types[i].type + '\'>' + types[i].displayName + '</option>');
			}
			
			// Static initializer
			Widget.Utils.initializeSingleton(Widget.UI.UnitEdit, this);
		},
		updateModel: function(model) {
			this._super(model);
			
			$('#unitEditView #unitType').val(model.type);
			$('#unitEditView #unitName').val(model.name);
			
			// Hide previous config panel
			if (typeof(this.configPanel) != 'undefined' && this.configPanel != null) {
				
				if (this.configPanel.model.type != model.type) {
					this.configPanel.enabled(false);
					this.configPanel = null;
				}
				
			}

			// Show new config panel
			if (this.configPanel == null) {
				var configPanelName = model.type.charAt(0).toUpperCase() + model.type.substring(1, model.type.length);
				configPanelName += 'ConfigPanel';
				
				if (eval('typeof(Widget.UI.' + configPanelName + ')') != 'undefined') {
					this.configPanel = eval('new Widget.UI.' + configPanelName + '();');
					this.configPanel.enabled(true);
				}
			}
			
			// Update config panel's model
			if (this.configPanel != null) {
				this.configPanel.updateModel(model);				
			}
		},
		edit: function(edit) {
			this._edit = edit;
			
			if (edit) {
				$('#unitEditView #listQuestions').show();
				$('#unitEditView #unitType').attr('disabled', 'true');
				$('#unitEditView #unitName').attr('disabled', 'true');
			} else {
				$('#unitEditView #listQuestions').hide();
				$('#unitEditView #unitType').removeAttr('disabled');
				$('#unitEditView #unitName').removeAttr('disabled');
			}
			
			if (typeof(this.configPanel) != 'undefined' &&  this.configPanel != null) {
				this.configPanel.edit(edit); 
			}
			
		},
		isEdit: function() {
			return this._edit;
		}
	});
	
	//Static methods & properties
	Widget.UI.UnitEdit._name = 'unitEditView';
	Widget.UI.UnitEdit.instance = function() {
		return Widget.Utils.singletonInstance(Widget.UI.UnitEdit, true);
	}
	
	Widget.UI.FileStoreConfigPanel = function() {
		$('#unitEditView #fileName').attr('disabled', 'true');
	
		this.updateModel = function(model) {
			this.model = model;
			
			var fileName = '';
			if (typeof(model.file()) != 'undefined' && model.file() != null) {
				
				var file = opera.io.filesystem.mountPoints.resolve(model.file());
				fileName = file.nativePath;
			}
			
			$('#unitEditView #fileName').val(fileName);
			
		}
		
		this.enabled = function(enabled) {
			if (enabled) {
				$('#unitEditView #fileStoreConfigPanel').show();
			} else {
				$('#unitEditView #fileStoreConfigPanel').hide();
			}
		}
		
		this.edit = function(edit) {
			this._edit = edit;
			if (edit) {
//				$('#unitEditView #fileName').attr('disabled', 'true');
				$('#unitEditView #fileChooser').attr('disabled', 'true');			
			} else {
//				$('#unitEditView #fileName').removeAttr('disabled');			
				$('#unitEditView #fileChooser').removeAttr('disabled');			
			}
		}
	}
	
	/**
	 * Question list view
	 */
	Widget.UI.QuestionListView = Widget.View.extend({
		
		// Constructor
		init: function() {
			this._super(Widget.UI.QuestionListView._name);
			
			/* Init the table */
			this.dataTable = $('#questionListView #answerList').dataTable({
				'bPaginate': false,
				'bLengthChange': false,
				'bFilter': false,
				'bSort': true,
				'bInfo': false,
				'bAutoWidth': false,
				'aoColumns': [ { 'bVisible': false }, null, null ]
			});			
			
			// Add a click handler to the rows - this could be used as a callback 
			fnInitTable(this.dataTable);
			
			var _self = this;
			function fnInitTable(_dataTable) {
				$('#questionListView #answerList tbody').click(function(event) {
					if (event.target.parentNode.nodeName.toLowerCase() == 'tr') {
						_self._selectItem(_dataTable, event.target.parentNode);
					}
				});
				$('#questionListView #answerListContainer #answerList_wrapper').addClass('tableContainer');
				$('#questionListView table#answerList').addClass('scrollTable');
				$('#questionListView #answerList thead').addClass('fixedHeader');
				$('#questionListView #answerList tbody').addClass('scrollContent');
			}
			
			
			// Static initializer
			Widget.Utils.initializeSingleton(Widget.UI.QuestionListView, this);
		},
		updateModel: function(model) {
			this.dataTable.fnClearTable();
			for (var i = 0; i < model.items().length; i++) {
				var item = model.items()[i];
				for (var j = 0; j < item.answers.length; j++) {
					this.dataTable.fnAddData([i, item.question, item.answers[j]]);
				}
			}
				
			if (model.items().length <= 0) {
				$('#questionListView #removeQuestion').addClass('disabled');
				$('#questionListView #modifyQuestion').addClass('disabled');
			} else {
				$('#questionListView #removeQuestion').removeClass('disabled');			
				$('#questionListView #modifyQuestion').removeClass('disabled');			
			}
				
				
			this.model = model;
		},
		selectedItem: function() {
			
			return fnGetSelected(this.dataTable, this.model);
			
			/* Get the rows which are currently selected */
			function fnGetSelected(_dataTable, _model) {
				var nodes = _dataTable.fnGetNodes();

				for (var i = 0; i < nodes.length; i++) {
					if ($(nodes[i]).hasClass('row_selected')) {
						return _dataTable.fnGetData(nodes[i])[0];
					}
				}
				
				return null;
			}			
			
		},
		selectRow: function(index) {
			var _self = this; 
			$('#questionListView #answerList tbody tr').each(function(i) {
				if (i == index) {
					_self._selectItem(_self.dataTable, this);
				}
			});
			
		},
		selectItem: function(index) {
			var node = this.dataTable.fnGetNodes(index);
			if (node) {
				this._selectItem(this.dataTable, node);
			}
		},
		itemsSize: function() {
			return this.dataTable.fnGetData().length;
		},
		_selectItem: function(_dataTable, _tr) {
			$(_dataTable.fnSettings().aoData).each(function() {
				$(this.nTr).removeClass('row_selected');
			});
			$(_tr).addClass('row_selected');
			
		}
	});
	
	//Static methods & properties
	Widget.UI.QuestionListView._name = 'questionListView';
	Widget.UI.QuestionListView.instance = function() {
		return Widget.Utils.singletonInstance(Widget.UI.QuestionListView, true);
	}	
	
	/**
	 * Question view
	 */
	Widget.UI.QuestionView = Widget.View.extend({
		
		// Constructor
		init: function() {
			this._super(Widget.UI.QuestionView._name);
			
			// Static initializer
			Widget.Utils.initializeSingleton(Widget.UI.QuestionView, this);
		},
		updateModel: function(model) {
			this._super(model);
			
			$('#questionView #question').val(model.question);
			$('#questionView #answers').val(model.answers.join('\n'));
		},
		edit: function(edit) {
			this._edit = edit;
		},
		isEdit: function() {
			return this._edit;
		}
	});
	
	//Static methods & properties
	Widget.UI.QuestionView._name = 'questionView';
	Widget.UI.QuestionView.instance = function() {
		return Widget.Utils.singletonInstance(Widget.UI.QuestionView, true);
	}
	
	/**
	 * Challenge view
	 */
	Widget.UI.ChallengeView = Widget.View.extend({
		
		// Constructor
		init: function() {
			this._super(Widget.UI.ChallengeView._name);
			
			// Static initializer
			Widget.Utils.initializeSingleton(Widget.UI.ChallengeView, this);
		},
		updateModel: function(model) {
			this._super(model);

			if (typeof(this.model) != 'undefined' && this.model.autoChallenge) {
				$('#challengeView #stopChallenge').show();
			} else {
				$('#challengeView #stopChallenge').hide();
			}

			$('#challengeView #challenge').val(model.question);
			$('#challengeView #answer').val(model.answer);
			$('#challengeView #correctAnswers').val(model.correctAnswers.join('\n'));
			$('#challengeView #correct').html(model.stat.correct);
			$('#challengeView #wrong').html(model.stat.wrong);
		},
		answered: function(result) {
			if (result) {
				$('#challengeView #checkAnswer').hide();
				$('#challengeView #nextChallenge').show();
				$('#challengeView #resultContainer').show();
				$('#challengeView #answer').attr('disabled', 'true');
			} else {
				$('#challengeView #resultContainer').hide();
				$('#challengeView #checkAnswer').show();
				$('#challengeView #nextChallenge').hide();
				$('#challengeView #answer').removeAttr('disabled');
			}
			this._result = result;
		},
		isAnswered: function() {
			return this._result;
		}
	});
	
	//Static methods & properties
	Widget.UI.ChallengeView._name = 'challengeView';
	Widget.UI.ChallengeView.instance = function() {
		return Widget.Utils.singletonInstance(Widget.UI.ChallengeView, true);
	}	
	
	/**
	 * UIManager
	 */
	Widget.UIManager = function() {
		
		var STRATEGY_NONE = 0;
		var STRATEGY_PUSH = 1;
		var STRATEGY_POP = 2;
		var STRATEGY_GOBACK = 3;
		
		var _views = [null];
		
		this.show = function(view, back, callback) {
			_show(back ? STRATEGY_PUSH : STRATEGY_NONE, view);
			if (typeof(callback) != 'undefined' && callback != null) {
				callback();
			}
		}
		
		Class.addMethod(this, 'back', function(callback) {
			_show(STRATEGY_POP);
			if (typeof(callback) != 'undefined' && callback != null) {
				callback();
			}
		});
		
		Class.addMethod(this, 'back', function(view, callback) {
			_show(STRATEGY_GOBACK, view);
			if (typeof(callback) != 'undefined' && callback != null) {
				callback();
			}
		});
		
		this.current = function() {
			return _views[_views.length - 1];
		}
		
		this.close = function() {
			window.close();
		}
		
		function _showControls(view) {
			var controlBar = $('ul#' + view.name + 'ControlBar');
			
			controlBar.html('');
			_appendControl(controlBar, 'closeButton');
			if (_views.length > 1) {
				_appendControl(controlBar, 'backButton');
			}
			$.each(view.controls(), function(index, control) {
				_appendControl(controlBar, control);
			});
			
		}
		
		function _appendControl(controlBar, control) {
			controlBar.append('<li class=\'' + control + ' button\'></li>');
		}
		
		function _show(strategy, view) {

			var previousView;
			if (strategy != STRATEGY_POP) {
				if (!(view instanceof Widget.View)) {
					throw new Error('not a view object');
				}
			}
			
			// Current view?
			if (strategy == STRATEGY_PUSH) {
				previousView = _views[_views.length - 1];
				_views.push(view);
			} else if (strategy == STRATEGY_POP) {
				if (_views.length > 0) {
					previousView = _views.pop();
				}
				view = _views[_views.length - 1];
			} else if (strategy == STRATEGY_GOBACK) {

				var foundView = null;
				for (var i = 0; i < _views.length; i++) {
					if (_views[i] == view) {
						
						foundView = _views[i];
						previousView = _views[_views.length - 1];
						_views = _views.slice(0, i + 1);
						break;
						
					}
				}
				
				if (!foundView) {
					throw new Error('No view found');
				}
				
				// FIXME: throw an error if no view found
				
			} else {
				previousView = _views[_views.length - 1];
				_views[_views.length - 1] = view;
			}
			        
			// Hide the previous view
			if (typeof(previousView) != 'undefined' && previousView != null) {
				
				if (previousView != view) {
					previousView._onHide();
					$('#' + previousView.name).hide();
				}
			}
			
			// Set window size
			var preferedSize = view.preferedSize();
			//window.resizeTo(preferedSize.width, preferedSize.height);
			
			view._onShow();
			_showControls(view);
			$('#' + view.name).show();
			
			
		}
		
		function _init() {
			Widget.Utils.initializeSingleton(Widget.UIManager, this);
		}
		
		// Initializer
		_init();
	
	};
	
	// Static methods & methods
	Widget.UIManager.instance = function() {
		
		return Widget.Utils.singletonInstance(Widget.UIManager, true);	
	
	}
	
})();